package kr.ne.jay.SimpleString;

import java.util.Iterator;
import java.util.Vector;

import android.graphics.Path;

public class SimString {
	private static final float	gEarth=981.f;
	public Vector<VerletPoint>	points;
	public Vector<IConstraint>	constraints;
	private long				m_lastTime;
	private Path				path;
	TouchConstraint				m_touchConstraint;
	Vector2f					g;
	
	public SimString() {
		points		= new Vector<VerletPoint>();
		constraints = new Vector<IConstraint>();
		path		= new Path();
		g			= new Vector2f(0, gEarth);
	}
	
	public void clear() {
		points.clear();
	}
	
	public void addPoint(Vector2f pos) {
		points.add(new VerletPoint(pos, pos));
	}
	
	public void addAcceleration(Vector2f a) {
		g.set(new Vector2f(0, gEarth));
		g.acc(a);
	}
	
	public float[] getLines() {
		float[] lines = null;
		int lineCount = points.size()-1;
		if (lineCount>1) {
			lines = new float[lineCount*4];
			for (int i=0; i<lineCount; ++i) {
				Vector2f pos1 = points.elementAt(i).pos;
				Vector2f pos2 = points.elementAt(i+1).pos;
				lines[4*i]   = pos1.x;
				lines[4*i+1] = pos1.y;
				lines[4*i+2] = pos2.x;
				lines[4*i+3] = pos2.y;
			}
		}
		return lines;
	}
	
	public Path getPath() {
		path.rewind();
		Iterator<VerletPoint> it = points.iterator(); 
		if (it.hasNext()) {
			Vector2f p = it.next().pos;
			path.moveTo(p.x, p.y);
		}
		Vector2f p;
		while (it.hasNext()) {
			p = it.next().pos;
			path.lineTo(p.x, p.y);
		}
		path.close();
		return path;
	}
	
	public void init() {
		initConstraint();
		m_lastTime = System.currentTimeMillis();		
	}
	
	private void initConstraint() {
		constraints.add(new FixedPosConstraint(0, points.elementAt(0).pos));

		int lineCount = points.size()-1;
		for (int i=0; i<lineCount; ++i) {
			Vector2f v1 = points.elementAt(i).pos;
			Vector2f v2 = points.elementAt(i+1).pos;
			constraints.add(new SimpleLinkConstraint(i, i+1, v1.dist(v2)));
		}
		
		constraints.add(new WallConstraint(0));
		constraints.add(new WallConstraint(1));
	}
	
	private void step(float dt) {
		verlet(dt);
		calcConstraints();
	}

	private float getDt() {
		long curTime = System.currentTimeMillis();
		float dt = (curTime-m_lastTime)*0.001f;
		if (dt>0.03f)
			dt = 0.03f;
		return dt;
	}

	public void clearLastTime() {
		m_lastTime = System.currentTimeMillis();
	}
	
	public void update() {
		step(getDt());
		m_lastTime = System.currentTimeMillis();
	}
	
	private void verlet(float dt) {
		Iterator<VerletPoint> it = points.iterator();
		while (it.hasNext()) {
			it.next().verlet(dt, g);
		}
	}
	
	private void calcConstraints() {
		for (int i=0; i<4; ++i) {
			Iterator<IConstraint> it = constraints.iterator();
			while (it.hasNext()) {
				IConstraint constraint = it.next();
				constraint.calcConstraint(points);
			}
			if (m_touchConstraint != null) {
				m_touchConstraint.calcConstraint(points);
			}
		}
	}

	public void AddTouchConstraint(Vector2f pos) {
		m_touchConstraint = new TouchConstraint(pos);		
	}
	
	public void MoveTouchConstraint(Vector2f pos) {
		m_touchConstraint.setPos(pos);
	}

	public void RemoveTouchConstraint() {
		m_touchConstraint = null;
	}
}
